package com.xingchi.tornado.security.provider;

import com.xingchi.tornado.security.exception.UserPermissionNotFoundException;
import com.xingchi.tornado.security.model.IUser;
import com.xingchi.tornado.security.model.LoginData;
import com.xingchi.tornado.security.model.UnifiedAuthenticationToken;
import com.xingchi.tornado.security.service.PermissionService;
import com.xingchi.tornado.security.service.RoleService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

/**
 * 抽象的认证处理器，处理认证处理器中的通用功能
 *
 * @author xiaoya
 * @date 2025/8/5 11:21
 */
@Slf4j
public abstract class AbstractAuthenticationProvider implements AuthenticationProvider, InitializingBean {

    @Autowired(required = false)
    private RoleService<?> roleService;
    @Autowired(required = false)
    private PermissionService<?> permissionService;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {

        // 执行认证处理
        LoginData<? extends IUser> loginData = authenticateHandler(authentication);

        // 获取并填充用户权限
        CompletableFuture<List<String>> userPermissionCodeFuture = CompletableFuture.supplyAsync(() -> {
            if (permissionService == null) {
                return Lists.newArrayList();
            }
            return permissionService.getUserPermissionCodes(loginData.getUserId());
        });
        CompletableFuture<List<String>> userRoleCodeFuture = CompletableFuture.supplyAsync(() -> {
            if (roleService == null) {
                return Lists.newArrayList();
            }
            return roleService.getUserRoleCode(loginData.getUserId());
        });
        CompletableFuture.allOf(userPermissionCodeFuture, userRoleCodeFuture).join();
        try {
            List<String> permissionCodeList = userPermissionCodeFuture.get();
            List<String> roleCodeList = userRoleCodeFuture.get();
            loginData.setRoleCodeList(new ArrayList<>(roleCodeList));
            loginData.setPermissionCodeList(new ArrayList<>(permissionCodeList));
        } catch (InterruptedException | ExecutionException e) {
            log.error("用户登录-权限获取失败，原因：{}", e.getMessage(), e);
            throw new UserPermissionNotFoundException("获取用户权限失败");
        }
        // 构建统一的认证信息对象
        return new UnifiedAuthenticationToken(loginData);
    }

    public abstract LoginData<? extends IUser> authenticateHandler(Authentication authentication) throws AuthenticationException;


    @Override
    public void afterPropertiesSet() throws Exception {

        if (roleService == null) {
            log.warn("未配置角色服务，请检查是否配置了角色服务");
        }

        if (permissionService == null) {
            log.warn("未配置权限服务，请检查是否配置了权限服务");
        }
    }
}
